import { message } from "antd"
import axios, { AxiosError, AxiosHeaders, AxiosRequestConfig, AxiosResponse } from "axios"

// 初始化各项目特殊全局配置
let init = false
const initConfig: Partial<InitConfig> = {
  devlog: true,
  messageHandler(message, errCode) {
    alert(`message:${message},errCode:${errCode}`)
  }
}

const request = axios.create({
  headers: {
    platFormId: "4fc40d89c02a42489346e5d2eaac9444",
    Equipment: "Web",
    ClientSystem: "Web",
    ClientType: "Web_backstage"
  }
})

const safeServerApiList = [
  "/safe/api/statistics/planStudySituationList2",
  "/safe/api/statistics/planStudySituationListByEnt",
  "/safe/api/statistics/getCycleStudyList",
  "/safe/api/statistics/getEntCycleStudyList",
  "/safe/api/statistics/assStudyPersonList2",
  "/safe/api/statistics/entStudyPersonList"
]

request.interceptors.response.use((res: AxiosResponse<ResponseResult<unknown>, unknown>) => {
  const { data, request, config } = res
  // responseType === "blob":如果响应体是2进制格式,则手动处理一下
  // application/octet-stream':后端返回的是字节流（浏览器默认处理方式是下载）
  if (
    (config.responseType === "blob" && data instanceof Blob) ||
    ((res.headers["content-type"] === "application/octet-stream" ||
      res.headers["content-type"] === "application/json") &&
      (config as any).getJsonFile)
  ) {
    res.data = {
      suc: true,
      data: data as unknown,
      errCode: "0",
      message: "请求成功",
      status: 0,
      go: undefined,
      total: undefined
    }
  }
  if (res.config.url && safeServerApiList.includes(res.config.url) && (res.data as any).code === 200) {
    res.data.suc = true
  }
  if (res.data.suc) {
    return res
  } else {
    return Promise.reject(new AxiosError(res.data.message, res.data.errCode, config, request, res))
  }
})

type CreateUserMethodParams = Pick<AxiosRequestConfigExpand<unknown>, "headers" | "method"> & { getJsonFile?: boolean }
// 创建一个请求方法实例
function createUserMethod(mergeConfig: CreateUserMethodParams) {
  return function userMethod<R = undefined, D = unknown>(
    url: string,
    data?: D,
    config?: Omit<AxiosRequestConfigExpand<D>, "data">
  ) {
    return request<ResponseResult<R>, AxiosResponse<ResponseResult<R>, D>, D>({
      url,
      data: mergeConfig.method === "POST" ? data : undefined,
      params: mergeConfig.method === "GET" ? data : undefined,
      ...mergeConfig,
      ...config,
      headers: Object.assign(
        new AxiosHeaders({
          ...initConfig.getHeaders?.()
        }),
        mergeConfig.headers,
        config?.headers
      )
    })
      .then((response) => {
        const logibeatResponseResult = response.data
        const config = Object.assign({}, initConfig, response.config)
        if (config.devlog) {
          // console.log(`请求接口:${config.url}`)
          // console.log(`请求响应:`, logibeatResponseResult)
        }

        if (logibeatResponseResult.suc) {
          config.showMsg && message.success(logibeatResponseResult.message)
          return logibeatResponseResult
        } else {
          return Promise.reject(
            new AxiosError(logibeatResponseResult.message, logibeatResponseResult.errCode, config, request, response)
          )
        }
      })
      .catch((err: AxiosError<ResponseResult<R>, D>) => {
        const logibeatResponseResult = (err.response?.data ?? {
          suc: false,
          message: "网络错误",
          errCode: "Net_Work_Error",
          go: null,
          status: null,
          total: null
        }) as ResponseResult
        const config = Object.assign({}, initConfig, err.config)
        // 都需要处理这个异常
        if (config.messageHandler && !mergeConfig.getJsonFile) {
          config.messageHandler(
            logibeatResponseResult?.message ?? "网络异常",
            logibeatResponseResult?.errCode ?? "Net_Work_Error"
          )
        }
        return Promise.reject(err)
      })
  }
}

const getData = createUserMethod({
  method: "GET"
})

const getJson = createUserMethod({
  method: "GET",
  getJsonFile: true
})

const postParam = createUserMethod({
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" }
})

const postJson = createUserMethod({
  method: "POST",
  headers: { "Content-Type": "application/json;charset=UTF-8" }
})

const postForm = createUserMethod({
  method: "POST",
  headers: { "Content-Type": "multipart/form-data" }
})

/**
 * @desc 设置不同请求的头信息
 */
function defineAxiosExpandConfig(config: InitConfig) {
  if (init === false) {
    init = true
    Object.assign(initConfig, config)
  } else {
    console.warn("已经初始化过了无法二次初始化")
  }
}

export { defineAxiosExpandConfig, getData, getJson, postParam, postJson, postForm }
export type { ResponseResult, AxiosRequestConfigExpand }

/**
 * @desc 物流云体系最常规通用请求响应体结构
 */
interface ResponseResult<T = undefined> {
  /**
   * @desc 请求是否成功
   */
  suc: boolean
  /**
   * @desc 服务器错误码，通知后端进行错误排查
   */
  errCode: string
  /**
   * @desc 请求结果信息
   */
  message: string
  /**
   * @desc 请求体真实数据,可能没有
   */
  data: T
  /**
   * @deprecated 没用
   */
  status: number
  /**
   * @deprecated 没啥用
   */
  go: unknown
  /**
   * @desc 如果请求的是列表则可能是总数
   */
  total: T extends Array<unknown> ? number : undefined
}

type InitConfig = {
  // 全局统一请求头扩充添加
  getHeaders?: () => Record<"baseuserid" | "baseEntId" | "ClientType", string>
  // 统一的错误信息处理方法
  messageHandler?: ((message: string, errCode: string) => boolean | void) | false
  // 是否打印返回内容日志 @default=true
  devlog?: boolean
  showMsg?: boolean
  getJsonFile?: boolean
}

interface AxiosRequestConfigExpand<D> extends AxiosRequestConfig<D>, InitConfig {}
